using WebSocketSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Newtonsoft.Json;
using pd2_server_sdk.server;
using ProtoBuf;
using UnityEngine;
using ErrorEventArgs = WebSocketSharp.ErrorEventArgs;

namespace Paradogs2
{
    public class WSGameServerConnection
    {
        public static WebSocket ws;
        private static long auto_id = 1;
        // Request() 的回调等待队列
        private static Dictionary<long, TaskCompletionSource<GC>> requestCallback = new ();

        public WSGameServerConnection(string url)
        {
            // 创建WebSocket实例
            ws = new WebSocket(url);

            // 订阅事件
            ws.OnOpen += OnOpen;
            ws.OnMessage += OnMessage;
            ws.OnError += OnError;
            ws.OnClose += OnClose;
        }

        // 连接到WebSocket服务器
        public async Task<bool> Connect()
        {
            TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
            EventHandler onOpen = (sender, e) =>
            {
                taskCompletionSource.SetResult(true);
            };
            EventHandler<WebSocketSharp.ErrorEventArgs> onError = (sender, e) =>
            {
                taskCompletionSource.SetResult(false);
            };
            ws.OnOpen += onOpen;
            ws.OnError += onError;
            ws.Connect();
            return await taskCompletionSource.Task;
        }

        // 发送消息
        public static void Send(string route, object message)
        {
            if (ws.IsAlive)
            {
                using (MemoryStream stream1 = new MemoryStream())
                {
                    using (MemoryStream stream2 = new MemoryStream())
                    {
                        Serializer.Serialize(stream1, message);
                        byte[] bytes = stream1.ToArray();

                        ByteMessage byteMessage = new ByteMessage();
                        byteMessage.header = new MessageHeader();
                        byteMessage.header.id = auto_id++;
                        byteMessage.header.server = "gs";
                        byteMessage.header.route = route;
                        byteMessage.dataBytes = bytes;
                        Serializer.Serialize(stream2, byteMessage);

                        ws.Send(stream2.ToArray());
                        Debug.Log("Send Message ... ");
                    }
                }
            }
            else
            {
                Debug.Log("WebSocket连接未建立，无法发送消息。");
            }
        }

        public static async Task<T> Request<T>(string route, object message)
        {
            if (ws.IsAlive)
            {
                using (MemoryStream stream1 = new MemoryStream())
                {
                    using (MemoryStream stream2 = new MemoryStream())
                    {
                        Serializer.Serialize(stream1, message);
                        byte[] bytes = stream1.ToArray();

                        ByteMessage byteMessage = new ByteMessage();
                        byteMessage.header = new MessageHeader();
                        byteMessage.header.id = auto_id++;
                        byteMessage.header.server = "gs";
                        byteMessage.header.route = route;
                        byteMessage.dataBytes = bytes;
                        Serializer.Serialize(stream2, byteMessage);

                        // 记录回调等待
                        var cb = new TaskCompletionSource<GC>();
                        requestCallback[byteMessage.header.id] = cb;

                        // 发送消息
                        ws.Send(stream2.ToArray());
                        Debug.Log($"发送消息 | route: {route}, id: {byteMessage.header.id}, data: {JsonConvert.SerializeObject(message)}");
                        GC gc = await cb.Task;
                        if (gc.data.Length > 0)
                        {
                            using (MemoryStream ackDataStream = new MemoryStream(gc.data))
                            {
                                T data = Serializer.Deserialize<T>(ackDataStream);
                                return data;
                            }
                        }
                        return default(T);
                    }
                }
            }
            else
            {
                Debug.Log("WebSocket连接未建立，无法发送消息。");
            }
            return default(T);
        }

        // 关闭连接
        public void Close()
        {
            if (ws.IsAlive)
            {
                ws.Close();
            }
        }

        // 处理连接打开事件
        private void OnOpen(object sender, EventArgs e)
        {
            Debug.Log("WebSocket连接已打开。");
        }

        // 处理接收到的消息事件
        private void OnMessage(object sender, MessageEventArgs e)
        {

            try
            {
                using (MemoryStream deserializeStream = new MemoryStream(e.RawData))
                {
                    ByteMessage byteMessage = Serializer.Deserialize<ByteMessage>(deserializeStream);
                    Debug.Log($"接收消息 | {byteMessage}");

                    // 理由 _net.gc 在这直接特殊处理
                    if (byteMessage.header.replyId != 0 && byteMessage.header.route == "_net.gc" && requestCallback.ContainsKey(byteMessage.header.replyId)) // not null
                    {
                        // _net.gc 回调唤醒对应异步等待的线程
                        if (requestCallback.ContainsKey(byteMessage.header.replyId))
                        {
                            using (MemoryStream dataBytesStream = new MemoryStream(byteMessage.dataBytes))
                            {
                                TaskCompletionSource<GC> cb = requestCallback[byteMessage.header.replyId];
                                GC gc = Serializer.Deserialize<GC>(dataBytesStream);
                                cb.TrySetResult(gc);
                            }
                        }
                    }
                    else
                    {
                        // 其余路由转发到对应路由处理器
                        try
                        {
                            Router.ExecuteRoute(byteMessage.header.route, byteMessage.dataBytes);
                        }
                        catch (Exception exception)
                        {
                            Debug.LogError(exception);
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                Debug.LogError(exception);
            }

        }

        // 处理错误事件
        private void OnError(object sender, ErrorEventArgs e)
        {
            Debug.Log($"发生错误: {e.Message}");
        }

        // 处理连接关闭事件
        private void OnClose(object sender, CloseEventArgs e)
        {
            Debug.Log($"WebSocket连接已关闭，代码: {e.Code}，原因: {e.Reason}");
        }
    }
}
